package com.request.service.impl.shop.jh;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.request.common.constants.RedisConstant;
import com.request.common.convert.PhoneOperatorConvert;
import com.request.common.enums.SignTypeEnum;
import com.request.common.enums.UserTypeEnum;
import com.request.common.utils.HttpUtils;
import com.request.common.utils.SignUtils;
import com.request.entity.PhoneOrderAvailable;
import com.request.entity.PhoneOrderWaitPush;
import com.request.entity.out.PushOrderForJH;
import com.request.service.PushOrderProcessor;
import com.request.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 * Create DateTime: 2020-04-22 16:09
 *
 * 

 */
@Slf4j
@Service
public class JHPushOrderProcessor implements PushOrderProcessor {

    private static final Map<String, String> HEADER_MAP = new HashMap<>(2);

    static {
        HEADER_MAP.put("Content-Type", "application/json;charset=utf-8");
    }

    @Resource
    private RedisService redisService;

    @Resource
    private ThreadPoolExecutor handlerOrderExecutor;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void sendRequest(PhoneOrderWaitPush phoneOrderWaitPush) {
        handlerOrderExecutor.execute(() -> executeSend(phoneOrderWaitPush));
    }

    private void executeSend(PhoneOrderWaitPush phoneOrderWaitPush) {
        PushOrderForJH pushOrderForJH = new PushOrderForJH();
        PhoneOrderAvailable pa = phoneOrderWaitPush.getPhoneOrderAvailable();
        String result = null;
        try {


            TreeMap<String, String> data = new TreeMap<>();
            String timeStr = String.valueOf(System.currentTimeMillis());
            String initSign = "appid=" + phoneOrderWaitPush.getAppId()
                    + "&appsecret=" + phoneOrderWaitPush.getAppKey()
                    + "&facevalue=" + pa.getOrderPrice().intValue()
                    + "&operatorcode=" + PhoneOperatorConvert.setPhoneOperator(pa.getPhoneOperator())
                    + "&timestr=" + timeStr;
            data.put("sign", initSign);
            String sign = SignUtils.generateSignature(data, SignTypeEnum.MD5);

            List<Map<String, String>> cardsList = new ArrayList<>();
            Map<String, String> map = new HashMap<>();
            map.put("account", pa.getPhoneNum());
            cardsList.add(map);

            pushOrderForJH.setAppId(phoneOrderWaitPush.getAppId())
                    .setInterfaceSecretKey(phoneOrderWaitPush.getAppKey())
                    .setCardsList(cardsList)
                    .setDiscount((int) (phoneOrderWaitPush.getRate() * 10000))
                    .setFaceValue(pa.getOrderPrice())
                    .setOperatorCode(PhoneOperatorConvert.setPhoneOperator(pa.getPhoneOperator()))
                    .setSign(sign.toLowerCase())
                    .setTimeStr(timeStr)
                    .setUserOrderNumber(pa.getPlatformOrderNo())
                    .setUserPlatUrl(phoneOrderWaitPush.getShopCallbackSite())
                    .setUserType(UserTypeEnum.COMPANY.getData())
                    .setWaitTime(pa.getOrderExpireTime());

            try {
                result = sendRequestForPushOrder(phoneOrderWaitPush.getPushSite(), pushOrderForJH);
            } catch (Exception e) {
                savePushOrderForException(phoneOrderWaitPush);
                log.info("【JH】【推单】发送请求出现异常：", e);
                return;
            }

            JSONObject jsonResult = JSON.parseObject(result);
            int ret = jsonResult.getIntValue("ret");
            if (ret != 0) {
                throw new RuntimeException("响应的状态码ret为 :" + ret);
            }
            savePushOrderForSuccess(pa.getPlatformOrderNo());
        } catch (Exception e) {
            savePushOrderForSuccess(pa.getPlatformOrderNo());
            log.error("【JH】【推送订单】推送订单失败，待推送订单信息为：{}, 请求参数为：{}, 商户响应结果为：{}, 详细错误信息为：",
                    phoneOrderWaitPush, pushOrderForJH, result, e);
        }
    }

    /**
     * 发送Http请求
     *
     * @param url            请求路径
     * @param pushOrderForJH 参数
     * @return 响应结果
     */
    private String sendRequestForPushOrder(String url, PushOrderForJH pushOrderForJH) {
        Map<String, Object> paramMap = BeanUtil.beanToMap(pushOrderForJH);
        return HttpUtils.doPost(url, paramMap, HEADER_MAP);
    }

    /**
     * 放入失败队列
     */
    private void savePushOrderForFailed(PhoneOrderWaitPush phoneOrderWaitPush) {
        redisService.lPush(RedisConstant.PUSH_ORDER_WAIT_PUSH_RECORD, JSON.toJSONString(phoneOrderWaitPush));
    }

    /**
     * 放入成功队列
     */
    private void savePushOrderForSuccess(String platformOrderNo) {
        redisTemplate.opsForValue().set(RedisConstant.PUSH_ORDER_WAIT_PUSH_SUCCESS + platformOrderNo, platformOrderNo, 30, TimeUnit.MINUTES);
    }

    /**
     * 放入发送出现异常的队列
     */
    private void savePushOrderForException(PhoneOrderWaitPush phoneOrderWaitPush) {
        redisService.lPush(RedisConstant.PUSH_ORDER_WAIT_PUSH_EXCEPTION, JSON.toJSONString(phoneOrderWaitPush));
    }
}
